#include "DbPart.h"
#include "connectpool.h"
#include <sstream>
#include <vector>
#include "Game.h"
#include "Logic.h"


CDbPart::CDbPart():m_dbHandler(NULL)
{
}

CDbPart::~CDbPart()
{
}

bool CDbPart::getYmInfo(const std::string& tname, const std::string& ym, unsigned int& seq, int& delflag, int& nodataflag)
{
	ostringstream ossSQL;
	ossSQL << "select seq,delflag from "<< tname  << " where ym = \'"<< ym <<"\'";

	nodataflag = 0;
	if (m_dbHandler->m_pMysqlConn->GetConnect() == NULL)
	{
		m_dbHandler->m_strError = m_dbHandler->m_pMysqlConn->What();
		log_error("getYmInfo Error: %s\r Sql=%s \n", m_dbHandler->m_pMysqlConn->What().c_str(), ossSQL.str().c_str());

		return false;
	}
	if (m_dbHandler->m_pStore->Query(ossSQL.str()))
	{
		unsigned long count = m_dbHandler->m_pStore->RowCount();
		if (count == 0)
		{
			nodataflag = 1;
			log_error("ERROR getYmInfo uid=%d count=0");
			return false;
		}

		seq = m_dbHandler->m_pStore->GetItemLong(0, "seq");
		delflag = m_dbHandler->m_pStore->GetItemLong(0, "delflag");
		log_debug("getYmInfo from db SQL=%s, count=%d,seq= %d", ossSQL.str().c_str(), count, seq);

		return true;
	}	
	else
	{
		log_error("Sql execution failed SQL=%s \n", ossSQL.str().c_str());
	}

	return false;
}


bool CDbPart::getYmInfoFrommSeq(const std::string& tname, const unsigned int seq, std::string& ym, int& delflag, int& nodataflag)
{
	ostringstream ossSQL;
	ossSQL << "select ym,delflag from "<< tname <<" where seq = " << seq;

	nodataflag = 0;
	if (m_dbHandler->m_pMysqlConn->GetConnect() == NULL)
	{
		m_dbHandler->m_strError = m_dbHandler->m_pMysqlConn->What();
		log_error("getAsset Error: %s\r Sql=%s \n", m_dbHandler->m_pMysqlConn->What().c_str(), ossSQL.str().c_str());

		return false;
	}
	if (m_dbHandler->m_pStore->Query(ossSQL.str()))
	{
		unsigned long count = m_dbHandler->m_pStore->RowCount();
		if (count == 0)
		{
			nodataflag = 1;
			log_error("ERROR getAsset uid=%d count=0");
			return false;
		}

		ym = m_dbHandler->m_pStore->GetItemString(0, "ym");
		delflag = m_dbHandler->m_pStore->GetItemLong(0, "delflag");
		log_debug("getYmInfo from db SQL=%s, count=%d,seq= %d,ym=%s,delflag=%d", ossSQL.str().c_str(), count, seq, ym.c_str(), delflag);

		return true;
	}	
	else
	{
		log_error("Sql execution failed SQL=%s \n", ossSQL.str().c_str());
	}

	return false;
}

bool CDbPart::getLastMonth(const std::string& tname, std::string& ym, unsigned int& seq, int& delflag, int& nodataflag)
{
	ostringstream ossSQL;
	ossSQL << "select ym,seq,delflag from " << tname << " order by seq desc limit 1";

	nodataflag = 0;
	delflag = 0;
	if (m_dbHandler->m_pMysqlConn->GetConnect() == NULL)
	{
		m_dbHandler->m_strError = m_dbHandler->m_pMysqlConn->What();
		log_error("getAsset Error: %s\r Sql=%s \n", m_dbHandler->m_pMysqlConn->What().c_str(), ossSQL.str().c_str());

		return false;
	}
	if (m_dbHandler->m_pStore->Query(ossSQL.str()))
	{
		unsigned long count = m_dbHandler->m_pStore->RowCount();
		if (count == 0)
		{
			nodataflag = 1;
			log_error("ERROR getFirstMonth count=0");
			return false;
		}

		ym = m_dbHandler->m_pStore->GetItemString(0, "ym");
		seq = m_dbHandler->m_pStore->GetItemLong(0, "seq");
		delflag = m_dbHandler->m_pStore->GetItemLong(0, "delflag");

		log_debug("getFirstMonth from db SQL=%s, ym-%s,seq= %u", ossSQL.str().c_str(), ym.c_str(), seq);
		return true;
	}	
	else
	{
		log_error("Sql execution failed SQL=%s \n", ossSQL.str().c_str());
	}

	return false;
}

bool CDbPart::createRecordTable(const std::string& tname) 
{
	ostringstream ossSQL;
	ossSQL << "CREATE TABLE IF NOT EXISTS `"<< tname<< "`(`seq` BIGINT UNSIGNED NOT NULL auto_increment,`uid` INT UNSIGNED NOT NULL DEFAULT 0,`useq` INT UNSIGNED NOT NULL DEFAULT 0,`roundid` VARCHAR(30) NOT NULL DEFAULT \'\', `bet` BIGINT NOT NULL DEFAULT 0, `betact` INT NOT NULL DEFAULT 0, `win` BIGINT NOT NULL DEFAULT 0, `winact` INT NOT NULL DEFAULT 0, `daybetamount` BIGINT NOT NULL DEFAULT 0, `daywinamount` BIGINT NOT NULL DEFAULT 0,`tt` BIGINT UNSIGNED NOT NULL DEFAULT 0, `dayfirstflag` INT NOT NULL DEFAULT 0, `detail` BLOB, `ext` BLOB, PRIMARY KEY (`seq`), INDEX idx_uid (`uid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4";

	if (!m_dbHandler->UpdateSql(ossSQL.str().c_str()))
	{
		m_dbHandler->m_strError = m_dbHandler->m_pMysqlConn->What();
		log_error("createRecordTable Error: %s\r Sql=%s \n", m_dbHandler->m_pMysqlConn->What().c_str(), ossSQL.str().c_str());

		return false;
	}

	return true;
}

bool CDbPart::getRecord(const std::string& tname, const _u64_ startseq, const unsigned int uid, const unsigned int reqnum, std::map<_u64_, stRecordItem>& record)
{
	ostringstream ossSQL;
	ossSQL << "select seq,useq,roundid,bet,betact,win,winact,daybetamount,daywinamount,tt,dayfirstflag,detail,ext from " << tname << " where uid = " << uid;
	if (startseq > 0)
	{
		ossSQL << " and seq <" << startseq;
	}
	ossSQL << " order by seq desc limit " << reqnum;

	if (m_dbHandler->m_pMysqlConn->GetConnect() == NULL)
	{
		m_dbHandler->m_strError = m_dbHandler->m_pMysqlConn->What();
		log_error("getRecord Error: %s\r Sql=%s \n", m_dbHandler->m_pMysqlConn->What().c_str(), ossSQL.str().c_str());

		return false;
	}
	if (m_dbHandler->m_pStore->Query(ossSQL.str()))
	{
		unsigned long count = m_dbHandler->m_pStore->RowCount();
		if (count == 0)
		{
			log_debug("getRecord uid=%u count=0", uid);
			return true;
		}

		for (int i = 0; i < count; ++i)
		{
			_u64_ seq = m_dbHandler->m_pStore->GetItemLongLong(i, "seq");
			unsigned int useq = m_dbHandler->m_pStore->GetItemLong(i, "useq");
			std::string roundid = m_dbHandler->m_pStore->GetItemString(i, "roundid");
			int64 bet = m_dbHandler->m_pStore->GetItemLongLong(i, "bet");
			int betact = m_dbHandler->m_pStore->GetItemLong(i, "betact");
			int64 win = m_dbHandler->m_pStore->GetItemLongLong(i, "win");
			int winact = m_dbHandler->m_pStore->GetItemLong(i, "winact");
			int64 daybetamount = m_dbHandler->m_pStore->GetItemLongLong(i, "daybetamount");
			int64 daywinamount = m_dbHandler->m_pStore->GetItemLongLong(i, "daywinamount");
			_u64_ tt = m_dbHandler->m_pStore->GetItemLongLong(i, "tt");
			int dayfirstflag = m_dbHandler->m_pStore->GetItemLong(i, "dayfirstflag");
			std::string detail = m_dbHandler->m_pStore->GetItemString(i, "detail");
			std::string ext = m_dbHandler->m_pStore->GetItemString(i, "ext");

			record.emplace(seq, stRecordItem(std::move(roundid), bet, betact, win, winact, tt, std::move(detail), daybetamount, daywinamount, dayfirstflag, useq, 0, std::move(ext)));
		}
		
		log_debug("getYmInfo from db SQL=%s, count=%d,uid= %d", ossSQL.str().c_str(), count, uid);

		return true;
	}	
	else
	{
		log_error("Sql execution failed SQL=%s \n", ossSQL.str().c_str());
	}

	return false;
}

bool CDbPart::getRecordDetail(const std::string& tname, const _u64_ seq, const unsigned int uid, std::string& detail, int& nodataflag)
{
	ostringstream ossSQL;
	ossSQL << "select detail from " << tname << " where seq = " << seq;

	nodataflag = 0;
	if (m_dbHandler->m_pMysqlConn->GetConnect() == NULL)
	{
		m_dbHandler->m_strError = m_dbHandler->m_pMysqlConn->What();
		log_error("getRecordDetail Error: %s\r Sql=%s \n", m_dbHandler->m_pMysqlConn->What().c_str(), ossSQL.str().c_str());

		return false;
	}
	if (m_dbHandler->m_pStore->Query(ossSQL.str()))
	{
		unsigned long count = m_dbHandler->m_pStore->RowCount();
		if (count == 0)
		{
			nodataflag = 1;
			return true;
		}

		for (int i = 0; i < count; ++i)
		{
			detail = m_dbHandler->m_pStore->GetItemString(i, "detail");
		}

		log_debug("getRecordDetail from db SQL=%s, count=%d,uid= %d", ossSQL.str().c_str(), count, uid);

		return true;
	}
	else
	{
		log_error("Sql execution failed SQL=%s \n", ossSQL.str().c_str());
	}

	return false;
}

bool CDbPart::getUserRecordCount(const std::string& tname, const unsigned int uid, const unsigned int mod, unsigned int& count, int& timezoneinmin, int& nodataflag)
{
	ostringstream ossSQL;
	ossSQL << "select count,timezoneinmin from " << tname << " where uid = " << uid;

	if (m_dbHandler->m_pMysqlConn->GetConnect() == NULL)
	{
		m_dbHandler->m_strError = m_dbHandler->m_pMysqlConn->What();
		log_error("getUserRecordCount Error: %s\r Sql=%s \n", m_dbHandler->m_pMysqlConn->What().c_str(), ossSQL.str().c_str());

		return false;
	}
	if (m_dbHandler->m_pStore->Query(ossSQL.str()))
	{
		unsigned long num = m_dbHandler->m_pStore->RowCount();
		if (num == 0)
		{
			count = 0;
			timezoneinmin = 0;
			nodataflag = 1;

			log_debug("getUserRecordCount uid=%u count=0", uid);
			return true;
		}

		count = m_dbHandler->m_pStore->GetItemLong(0, "count");
		timezoneinmin = m_dbHandler->m_pStore->GetItemLong(0, "timezoneinmin");
		nodataflag = 0;

		log_debug("getUserRecordCount from db SQL=%s, count=%u,uid= %u", ossSQL.str().c_str(), count, uid);

		return true;
	}
	else
	{
		log_error("Sql execution failed SQL=%s \n", ossSQL.str().c_str());
	}
	return false;
}


bool CDbPart::insertAndaddUserRecordCount(const unsigned int uid, const unsigned int mod, const unsigned int delt)
{
	ostringstream ossSQL;
	ossSQL << "insert into user_transactions_count_" << uid % mod << "(uid, count) values("<<uid<<","<<delt << ") ON DUPLICATE KEY UPDATE count = count+" << delt;

	if (!m_dbHandler->UpdateSql(ossSQL.str().c_str()))
	{
		m_dbHandler->m_strError = m_dbHandler->m_pMysqlConn->What();
		log_error("getAsset Error: %s\r Sql=%s \n", m_dbHandler->m_pMysqlConn->What().c_str(), ossSQL.str().c_str());

		return false;
	}

	return true;
}

bool CDbPart:: createGameRecordCountTable(const std::string& tname)
{ 
	ostringstream ossSQL;
	ossSQL << "CREATE TABLE IF NOT EXISTS `"<< tname<< "` (`uid` int unsigned NOT NULL DEFAULT 0,`count` int unsigned NOT NULL DEFAULT 0,`timezoneinmin` int NOT NULL DEFAULT 0, PRIMARY KEY (`uid`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci";

	if (!m_dbHandler->UpdateSql(ossSQL.str().c_str()))
	{
		m_dbHandler->m_strError = m_dbHandler->m_pMysqlConn->What();
		log_error("createGameRecordCountTable Error: %s\r Sql=%s \n", m_dbHandler->m_pMysqlConn->What().c_str(), ossSQL.str().c_str());

		return false;
	}

	return true;
}

bool CDbPart::createMonthListTable(const std::string& tname)
{
	ostringstream ossSQL;
	ossSQL << "CREATE TABLE IF NOT EXISTS `"<< tname<< "` (`ym` varchar(10) NOT NULL DEFAULT \'\',`seq` int unsigned NOT NULL,`delflag` int NOT NULL DEFAULT 0 COMMENT \'月数据删除标记\',PRIMARY KEY (`ym`) , UNIQUE KEY `idx_seq` (`seq`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci";

	if (!m_dbHandler->UpdateSql(ossSQL.str().c_str()))
	{
		m_dbHandler->m_strError = m_dbHandler->m_pMysqlConn->What();
		log_error("createMonthListTable Error: %s\r Sql=%s \n", m_dbHandler->m_pMysqlConn->What().c_str(), ossSQL.str().c_str());

		return false;
	}

	return true;
}

bool CDbPart::addTableRecord(const std::string& tname, const unsigned int game, const unsigned int ym, const unsigned int uidmod, const _u64_ rt)
{
	ostringstream ossSQL;
	ossSQL << "insert into gamerecord_table_record(tname, game, ym, uidmod, rt) values(\'" << tname << "\',"<< game <<","<< ym <<"," << uidmod << "," << rt << ") ON DUPLICATE KEY UPDATE uidmod=uidmod";

	if (!m_dbHandler->UpdateSql(ossSQL.str().c_str()))
	{
		m_dbHandler->m_strError = m_dbHandler->m_pMysqlConn->What();
		log_error("addTableRecord Error: %s\r Sql=%s \n", m_dbHandler->m_pMysqlConn->What().c_str(), ossSQL.str().c_str());

		return false;
	}

	return true;
}